package curl

import (
	"fmt"
	"io"
	"net"
	"net/http"
	"net/url"
	"strings"
	"syscall"
)

// Request represents an HTTP request
type Request struct {
	URL     string
	Method  string
	Headers http.Header
	Data    []byte
}

// Response represents an HTTP response
type Response struct {
	Status  string
	Headers string
	Body    string
}

// HTTPClient represents an HTTP client based on epoll
type HTTPClient struct {
	connFd  int
	request *http.Request

	// 请求相关缓冲区
	requestBuffer []byte

	// 响应相关缓冲区
	responseBuffer []byte
	response       *Response
}

// Do sends an HTTP request and returns the response
func (c *HTTPClient) Do(req *http.Request) int {
	c.request = req

	// 确定端口
	port := req.URL.Port()
	if port == "" {
		if req.URL.Scheme == "https" {
			port = "443"
		} else {
			port = "80"
		}
	}

	// 建立连接
	addr := req.URL.Hostname() + ":" + port
	conn, err := net.Dial("tcp", addr)
	if err != nil {
		return -1
	}

	// 获取文件描述符
	tcpConn, ok := conn.(*net.TCPConn)
	if !ok {
		conn.Close()
		return -1
	}

	// 获取原始网络连接的文件描述符
	rawConn, err := tcpConn.SyscallConn()
	if err != nil {
		conn.Close()
		return -1
	}

	// 通过控制函数获取文件描述符
	err = rawConn.Control(func(fd uintptr) {
		c.connFd = int(fd)
	})
	if err != nil {
		conn.Close()
		return -1
	}

	// 设置连接为阻塞模式
	if err := syscall.SetNonblock(c.connFd, false); err != nil {
		conn.Close()
		return -1
	}

	// 构造HTTP请求
	if err := c.buildHTTPRequest(req.URL); err != nil {
		conn.Close()
		return -1
	}

	requestSent := 0

	for {
		// 发送请求数据
		n, err := conn.Write(c.requestBuffer[requestSent:])
		if err != nil {
			// 检查是否是临时错误
			if netErr, ok := err.(net.Error); ok && netErr.Temporary() {
				return -1
			}
			// 检查是否是EAGAIN或EWOULDBLOCK错误
			if err == syscall.EAGAIN || err == syscall.EWOULDBLOCK {
				return -1
			}
			return -1
		}

		// 更新已发送的字节数
		requestSent += n

		// 检查是否发送完成
		if requestSent >= len(c.requestBuffer) {
			break
		}
	}

	return c.connFd
}

// buildHTTPRequest constructs the HTTP request
func (c *HTTPClient) buildHTTPRequest(parsedURL *url.URL) error {
	// 构造请求行
	requestLine := fmt.Sprintf("%s %s HTTP/1.1\r\n", c.request.Method, parsedURL.RequestURI())

	// 组合请求头
	var headerString strings.Builder
	headerString.WriteString(requestLine)
	for key, values := range c.request.Header {
		for _, value := range values {
			headerString.WriteString(fmt.Sprintf("%s: %s\r\n", key, value))
		}
	}
	headerString.WriteString("\r\n")

	// 组合完整请求
	var requestString strings.Builder
	requestString.WriteString(headerString.String())
	if c.request.Body != nil {
		body, err := io.ReadAll(c.request.Body)
		if err != nil {
			return fmt.Errorf("read request body error: %v", err)
		}
		requestString.Write(body)
	}

	c.requestBuffer = []byte(requestString.String())
	return nil
}

// parseResponse parses the HTTP response
func (c *HTTPClient) parseResponse() {
	if c.response.Status == "" { // 如果还没有解析过响应头
		headerEnd := strings.Index(c.response.Body, "\r\n\r\n") // 查找响应头结束位置
		if headerEnd == -1 {
			return // 还没有接收完整的响应头
		}

		// 解析响应行和响应头
		headers := c.response.Body[:headerEnd]
		lines := strings.Split(headers, "\r\n")

		if len(lines) > 0 {
			c.response.Status = lines[0]
			c.response.Headers = strings.Join(lines[1:], "\r\n")
		}

		c.response.Body = c.response.Body[headerEnd+4:] // 保存响应体
	} else {
		// 已经解析过响应头，继续累积响应体
		// 这里可以添加更复杂的逻辑来处理分块传输等
	}
}
